package com.computergames.server.protocol;

import com.computergames.server.message.Message;
import com.computergames.server.message.chessMessage.AbstractChessMessage;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.gson.*;
import org.springframework.stereotype.Component;

import java.io.*;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;

@Component
public enum SerializerEnum implements Serializer{
    Java{
        @Override
        public <T> byte[] serialize(T object) {
            try {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(object);
                return bos.toByteArray();
            } catch (IOException e) {
                throw new RuntimeException("序列化失败", e);
            }
        }
        @Override
        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            try {
                ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
                return (T) ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
                throw new RuntimeException("反序列化失败", e);
            }
        }
    },
    Gson{
        @Override
        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            // 创建GsonBuilder实例并注册所有必要的TypeAdapter
            GsonBuilder gsonBuilder = new GsonBuilder();

            // 注册ClassCodec
            gsonBuilder.registerTypeAdapter(Class.class, new ClassCodec());

            gsonBuilder.registerTypeAdapter(AbstractChessMessage.class, new AbstractChessMessageTypeAdapterFactory());

            gsonBuilder.registerTypeAdapter(Message.class, new MoveRequestMessageAdapterFactory());

            // 创建Gson实例
            Gson gson = gsonBuilder.create();

            // 将字节数组转换为字符串
            String json = new String(bytes, StandardCharsets.UTF_8);

            // 使用创建好的Gson实例进行反序列化
            return gson.fromJson(json, clazz);
        }

        @Override
        public <T> byte[] serialize(T object) {
            Gson gson = new GsonBuilder().registerTypeAdapter(Class.class, new ClassCodec()).create();
            String json = gson.toJson(object);
            return json.getBytes(StandardCharsets.UTF_8);
        }
    },
    Jackson{
        private static final ObjectMapper objectMapper;

        static {
            objectMapper = new ObjectMapper();
            // 配置 ObjectMapper，例如允许未知属性等
            objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

            // 注册自定义的反序列化器模块
            SimpleModule module = new SimpleModule();
            module.addDeserializer(Message.class, new AbstractGameMessageDeserializer());
            //module.addDeserializer(AbstractCardMessage.class, new CardMessageDeserializer());
            objectMapper.registerModule(module);
        }

        public <T> byte[] serialize(T object) {
            try {
                return objectMapper.writeValueAsBytes(object);
            } catch (IOException e) {
                throw new RuntimeException("序列化失败", e);
            }
        }

        public <T> T deserialize(Class<T> clazz, byte[] bytes) {
            if (bytes == null || bytes.length == 0) {
                throw new IllegalArgumentException("反序列化的字节数组不能为空");
            }
            try {
                return objectMapper.readValue(new String(bytes, StandardCharsets.UTF_8), clazz);
            } catch (IOException e) {
                throw new RuntimeException("反序列化失败", e);
            }
        }
    };

    static class ClassCodec implements JsonSerializer<Class<?>>, JsonDeserializer<Class<?>> {

        @Override
        public Class<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                String str = json.getAsString();
                return Class.forName(str);
            } catch (ClassNotFoundException e) {
                throw new JsonParseException(e);
            }
        }

        @Override             //   String.class
        public JsonElement serialize(Class<?> src, Type typeOfSrc, JsonSerializationContext context) {
            // class -> json
            return new JsonPrimitive(src.getName());
        }
    }
}
